package db

import (
	"github.com/kataras/iris/v12"
	"github.com/pkg/errors"
	"github.com/qf-tech/qftech-base/pkg/log"
	"github.com/uptrace/bun"
)

var App *app

type app struct {
}

type AppGetOptions struct {
	AppName     string
	AppID       string
	AppSecret   string
	IsFlag      int
	AccessToken string
	UserName    string
}

type AppUpdateOptions struct {
	AppName     string
	AppID       string
	AppSecret   string
	IsFlag      int
	AccessToken string
	UserName    string
}

type AppModel struct {
	bun.BaseModel `bun:"table:m_app"`

	ID          int64  `bun:"id,pk,autoincrement"`
	AppName     string `bun:"app_name"`
	AppID       string `bun:"app_id"`
	AppSecret   string `bun:"app_secret"`
	IsFlag      int    `bun:"is_flag"`
	AccessToken string `bun:"access_token"`
	UserName    string `bun:"user_name"`
}

func (a *app) Create(ctx iris.Context, opts AppUpdateOptions) error {
	appModel := AppModel{
		AppName:     opts.AppName,
		AppID:       opts.AppID,
		AppSecret:   opts.AppSecret,
		IsFlag:      opts.IsFlag,
		AccessToken: opts.AccessToken,
		UserName:    opts.UserName,
	}

	q := BunDb.NewInsert().Model(&appModel)

	_, err := q.Exec(ctx.Request().Context())
	if err != nil {
		return errors.Wrap(err, "create app")
	}
	return nil
}

func (a *app) Update(ctx iris.Context, opts AppUpdateOptions) error {
	value := make(map[string]interface{})
	if opts.AppName != "" {
		value["app_name"] = opts.AppName
	}

	if opts.AppSecret != "" {
		value["app_secret"] = opts.AppSecret
	}

	if opts.IsFlag >= 0 {
		value["is_flag"] = opts.IsFlag
	}

	if opts.AccessToken != "" {
		value["access_token"] = opts.AccessToken
	}

	_, err := BunDb.NewUpdate().
		Model(&value).
		TableExpr("m_app").
		Where("app_id = ?", opts.AppID).
		Exec(ctx.Request().Context())

	if err != nil {
		return errors.Wrap(err, "update app")
	}

	return nil
}

type AppResult struct {
	AppsInfo []*AppModel
}

func (a *app) Get(ctx iris.Context, opts AppGetOptions) (*AppResult, error) {
	log := log.GetLogger().GetCtx(ctx.Request().Context()).Sugar()

	whereFun := func(q *bun.SelectQuery) *bun.SelectQuery {
		q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
			if len(opts.AppID) > 0 {
				q.Where("app_id = ?", opts.AppID)
			}
			return q
		})

		q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
			if len(opts.AppSecret) > 0 {
				q.Where("app_secret = ?", opts.AppSecret)
			}
			return q
		})

		q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
			if opts.IsFlag > -1 {
				q.Where("is_flag = ?", opts.IsFlag)
			}
			return q
		})

		q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
			if len(opts.AccessToken) > 0 {
				q.Where("access_token = ?", opts.AccessToken)
			}
			return q
		})

		q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
			if len(opts.UserName) > 0 {
				q.Where("user_name = ?", opts.UserName)
			}
			return q
		})
		return q
	}

	result := AppResult{}

	q := BunDb.NewSelect().
		Model(&result.AppsInfo).
		ColumnExpr("*").
		WhereGroup(" AND ", whereFun)

	err := q.Scan(ctx.Request().Context())
	if err != nil {
		log.Errorf("get app info err: %v", err)
		return nil, err
	}

	return &result, nil
}

func (a *app) GetByUserName(ctx iris.Context, userName string) (*AppResult, error) {
	log := log.GetLogger().GetCtx(ctx.Request().Context()).Sugar()
	result := AppResult{}

	q := BunDb.NewSelect().
		Model(&result.AppsInfo).
		ColumnExpr("*").
		Where("user_name = ?", userName)

	err := q.Scan(ctx.Request().Context())
	if err != nil {
		log.Errorf("get app info err: %v", err)
		return nil, err
	}

	return &result, nil
}
